﻿#ifndef SERIAL_DEV_H
#define SERIAL_DEV_H

#include <QObject>
#include <QByteArray>
#include <QString>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QTimer>
#include <QVariant>
#include <QList>
#include <QQueue>
#include <QDebug>


#include <iostream>
#include <condition_variable>
#include <chrono>
#include <thread>
#include <mutex>
#include <memory>
#include <queue>
#include <atomic>

#define SIZE_HEAD 2
#define SIZE_TAIL 2
#define SIZE_LEN 2
#define SIZE_DEVADD 2
#define SIZE_FUCCODE 1
#define SIZE_PACKTOTAL 2
#define SIZE_PACKID 2


#define SIZE_RES 49
#define SIZE_CHK 2
#define SIZE_DATA 1024

#define SIZE_NOTDATA (SIZE_HEAD+SIZE_TAIL+SIZE_LEN+SIZE_DEVADD+SIZE_FUCCODE+SIZE_PACKTOTAL+SIZE_PACKID+SIZE_RES+SIZE_CHK)

#define CONCAT2b(a, b) (((a) << 8) | (b))

#define DATA_CHECK_HEAD         0
#define DATA_CHECK_LENGTH       1
#define DATA_CHECK_DEVADDR      2
#define DATA_CHECK_FUCCODE      3
#define DATA_CHECK_DATA         4
#define DATA_CHECK_CHECKSUM     5
#define DATA_CHECK_TAILER       6

#define DATA_HEAD_H             0x23U
#define DATA_HEAD_L             0x55U
#define DATA_TAIL_H             0x0dU
#define DATA_TAIL_L             0x0aU

#define DATA_FUNCODE_RANGE 0x40
#define DATA_FUNCODE_FFT   0x41
#define DATA_FUNCODE_RAW   0x42
#define DATA_FUNCODE_SPEED 0x43

#define DATA_TYPE_RANGE 1
#define DATA_TYPE_PINPU 2

class serial_dev : public QObject
{
    Q_OBJECT
public:
    explicit serial_dev(QObject *parent = nullptr);
    /*serial_dev(const serial_dev &other);*/
    ~serial_dev();
    //member
    std::unique_ptr<QSerialPort> drv;
    std::unique_ptr<QTimer> inner_timer;
    std::thread parse_thread;
    std::condition_variable cv;
    std::mutex mtx;
    std::atomic<bool> pause_flag = false;
    std::atomic<bool> open_flag = false;
    //std::atomic<int> get_pack = 0;


    std::shared_ptr<std::queue<uint8_t>> buf;
    QByteArray tempdata_pinpu;
    QByteArray revdata_pinpu;
    QByteArray revdata_pinpu_t;

    QByteArray tempdata_range;
    QByteArray revdata_range;
    //method
    int com_open(const QString& portname,const int baudrate);
    int com_close();
    bool status();
    QStringList refresh_port();
    void parse_task();
    int parse_process(uint8_t data, uint8_t* output_mode, uint16_t* output_devaddr);
    int parse_merge_pack(uint16_t funcode, uint8_t * output_mode);
signals:
    void get_pingpu_data(QByteArray* ptr, uint16_t* devaddr);
    void get_range_data(QByteArray* ptr);
    //void update_mode(int mode);

public slots:
    void com_rev();
    void timeout_handle();
};

#endif // SERIAL_DEV_H
